/***************************************************************
 *  Copyright (c) 2007 by GroupMe! Team (www.groupme.net)
 *  All rights reserved
 *
 *  This file is part of the GroupMe! Project. You can utilize
 *  software of the GroupMe! project under the terms of the 
 *  GNU Lesser General Public License as published by the
 *  Free Software Foundation in version 2.1.
 * 
 *  The GNU Lesser General Public License can be found at:
 *  http://www.gnu.org/licenses/lgpl.html
 *
 *  This copyright notice MUST APPEAR in all copies of the file!
 ***************************************************************/
package net.groupme.model;

import java.net.URI;
import java.net.URL;
import java.util.Collection;
import java.util.Iterator;
import java.util.Random;

import net.groupme.exceptions.DuplicateUsernameException;
import net.groupme.exceptions.InsertFailedException;
import net.groupme.exceptions.UpdateFailedException;
import net.groupme.exceptions.UserNotExistingException;
import net.groupme.gui.rendering.constants.RENDERING_CONSTANTS;
import net.groupme.model.cache.Cachable;
import net.groupme.model.cache.CachedObject;
import net.groupme.model.cache.CachedObjectType;
import net.groupme.model.dao.DBProperties;
import net.groupme.model.dao.GroupDAOImpl;
import net.groupme.model.dao.GroupVisualizationDAOImpl;
import net.groupme.model.dao.ResourceDAOImpl;
import net.groupme.model.dao.ResourceVisualizationDAOImpl;
import net.groupme.model.dao.StyleDAOImpl;
import net.groupme.model.dao.TagDAOImpl;
import net.groupme.model.dao.UserDAOImpl;
import net.groupme.model.dao.cache.CachedObjectDAOImpl;
import net.groupme.model.dao.mem.GroupDAOMemImpl;
import net.groupme.model.dao.mem.GroupVisualizationDAOMemImpl;
import net.groupme.model.dao.mem.ResourceDAOMemImpl;
import net.groupme.model.dao.mem.ResourceVisualizationDAOMemImpl;
import net.groupme.model.dao.mem.TagDAOMemImpl;
import net.groupme.model.dao.mem.UserDAOMemImpl;
import net.groupme.utils.ResourceTools;
import net.groupme.utils.StringUtilities;
import net.groupme.utils.sql.CacheQueryUtility;
import net.groupme.utils.sql.GetTagsQuery;
import net.groupme.utils.sql.SelectQueryUtility;

import org.apache.log4j.Logger;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.web.servlet.tags.EscapeBodyTag;

import com.mysql.jdbc.MysqlDataTruncation;
import com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource;

/**
 * 
 * This class provides method for creating Objects of the GroupMe! model.
 * 
 * 
 * @author Mischa Frank, <a
 *         href="mailto:code@planetfrank.net">code@planetfrank.net</a>
 * 
 * @version 1.0, created on 24.05.2007
 * 
 */
public class ObjectFactory {
	
	/** Logger for this class  */
	private static final Logger logger = Logger.getLogger(ObjectFactory.class);
	
	
	// table
	public static final String TABLE_TAG = DBProperties
			.getString("GroupmeDB.TABLE_TAG"); //$NON-NLS-1$

	// columns
	public static final String TAG_KEYWORD = DBProperties
			.getString("GroupmeDB.TAG_KEYWORD"); //$NON-NLS-1$
	
	public static final String TAG_ID = DBProperties
	.getString("GroupmeDB.TAG_ID"); //$NON-NLS-1$

	/** the data source (= backend for DAO implementation) */
	public static DriverManagerDataSource ds = new DriverManagerDataSource();
	static {
		ds.setDriverClassName(ObjectFactoryProperties.getString("ObjectFactoryProperties.DB_DRIVER")); //$NON-NLS-1$
		ds.setUrl(ObjectFactoryProperties.getString("ObjectFactoryProperties.DB_URL")); //$NON-NLS-1$
		ds.setUsername(ObjectFactoryProperties.getString("ObjectFactoryProperties.DB_USER")); //$NON-NLS-1$
		ds.setPassword(ObjectFactoryProperties.getString("ObjectFactoryProperties.DB_PW")); //$NON-NLS-1$
	}
	
	/**
	 * This method returns a Group object with default values.
	 * 
	 * @return Group
	 * @throws InsertFailedException
	 */
	public static final Group createGroup() throws InsertFailedException {
		return new GroupImpl(new GroupDAOImpl(ds, ObjectFactoryProperties.getString("ObjectFactoryProperties.DEFAULT_GROUP_NAME"), //$NON-NLS-1$
				ObjectFactoryProperties.getString("ObjectFactoryProperties.DEFAULT_GROUP_DESCRIPTION"))); //$NON-NLS-1$
	}

	/**
	 * This method retuns a Group object.
	 * 
	 * @param name
	 * @param description
	 * @return Group
	 * @throws InsertFailedException
	 */
	public static final Group createGroup(String name, String description)
			throws InsertFailedException {
		return new GroupImpl(new GroupDAOImpl(ds, name, description));
	}

	/**
	 * This method returns a GroupVisualization object with default values.
	 * 
	 * @return GroupVisualization
	 * @throws InsertFailedException
	 */
	public static final GroupVisualization createGroupVisualization()
			throws InsertFailedException {
		return new GroupVisualizationImpl(new GroupVisualizationDAOImpl(ds,
				ObjectFactoryProperties.getString("ObjectFactoryProperties.DEFAULT_GROUPVISUALIZATION_NAME"), //$NON-NLS-1$
				ObjectFactoryProperties.getString("ObjectFactoryProperties.DEFAULT_GROUPVISUALIZATION_DESCRIPTION"))); //$NON-NLS-1$
	}

	/**
	 * This method returns a GroupVisualization object.
	 * 
	 * @param name
	 * @param description
	 * @return GroupVisualization
	 * @throws InsertFailedException
	 */
	public static final GroupVisualization createGroupVisualization(
			String name, String description) throws InsertFailedException {
		return new GroupVisualizationImpl(new GroupVisualizationDAOImpl(ds,
				name, description));
	}
	
	/**
	 * This method returns a GroupVisualization object.
	 * 
	 * @param id the id of the GroupVisualization
	 * @return GroupVisualization corresponding GroupVisualization
	 * @throws InsertFailedException
	 */
	public static final GroupVisualization getGroupVisualization(
			String id) throws InsertFailedException {
		return new GroupVisualizationImpl(new GroupVisualizationDAOImpl(ds, id));
	}

	/**
	 * This method returns a Resource object.
	 * 
	 * @param name
	 * @param description
	 * @param type
	 *            (image, video, website, rss, group)
	 * @param url
	 * @return Resource
	 * @throws InsertFailedException
	 */
	public static final Resource createResource(String name,
			String description, String type, URL url)
			throws InsertFailedException {
		//check if resource already exists:
		String id = ResourceTools.doesResourceWithGivenUrlExists(url.toString());
		if(id != null){
			return getResource(id);
		}
		return new ResourceImpl(new ResourceDAOImpl(ds, name, description,
				type, url));
	}

	/**
	 * This method returns a Resource object with default name und description.
	 * 
	 * @param type
	 * @param url
	 * @return Resource
	 * @throws InsertFailedException
	 */
	public static final Resource createResource(String type, URL url)
			throws InsertFailedException {
		//check if resource already exists:
		String id = ResourceTools.doesResourceWithGivenUrlExists(url.toString());
		if(id != null){
			return getResource(id);
		}
		return new ResourceImpl(new ResourceDAOImpl(ds,
				ObjectFactoryProperties.getString("ObjectFactoryProperties.DEFAULT_RESOURCE_NAME"), ObjectFactoryProperties.getString("ObjectFactoryProperties.DEFAULT_RESOURCE_DESCRIPTION"), type, //$NON-NLS-1$ //$NON-NLS-2$
				url));
	}

	/**
	 * This method returns a Group object with default values.
	 * 
	 * @return Group
	 * @throws InsertFailedException
	 */
	public static final ResourceVisualization createResourceVisualization(
			String groupVisualizationID, String resourceID)
			throws InsertFailedException {
		int x = (new Random().nextInt(7))*100 + 20;
		int y = (new Random().nextInt(6))*100 + 20;
		int z = (int) ((System.currentTimeMillis()/1000) % 1000000);
		return new ResourceVisualizationImpl(new ResourceVisualizationDAOImpl(
				ds, groupVisualizationID, resourceID, x, y, 1000, 350, z, RENDERING_CONSTANTS.RENDERER_DEFAULT));
	}
	
	/**
	 * This method returns a Group object with default values.
	 * 
	 * @return Group
	 * @throws InsertFailedException
	 */
	public static final ResourceVisualization createResourceVisualization(
			GroupVisualization groupVisu, Resource resource)
			throws InsertFailedException {
		int x = (new Random().nextInt(7))*100 + 20;
		int y = (new Random().nextInt(6))*100 + 20;
		int z = (int) ((System.currentTimeMillis()/1000) % 1000000);
		return new ResourceVisualizationImpl(new ResourceVisualizationDAOImpl(
				ds, groupVisu.getId(), resource.getId(), x, y, 1000, 350, z, RENDERING_CONSTANTS.RENDERER_DEFAULT));
	}

	/**
	 * This method returns a ResourceVisualization object
	 * 
	 * @param groupVisualizationID
	 *            in which the ResourceVisualization is grouped
	 * @param resourceID
	 *            which the ResourceVisualization visualizes
	 * @param positionX
	 * @param positionY
	 * @param width
	 * @param heigth
	 * @return ResourceVisualization
	 * @throws InsertFailedException
	 */
	public static final ResourceVisualization createResourceVisualization(
			String groupVisualizationID, String resourceID, int posX, int posY,
			int width, int heigth) throws InsertFailedException {
		int z = (int) ((System.currentTimeMillis()/1000) % 1000000);
		return new ResourceVisualizationImpl(
				new ResourceVisualizationDAOImpl(ds, groupVisualizationID,
						resourceID, posX, posY, width, heigth, z, RENDERING_CONSTANTS.RENDERER_DEFAULT));
	}

	/**
	 * This method returns a Style object with default values.
	 * 
	 * @return Style
	 * @throws InsertFailedException
	 */
	public static final Style createStyle() throws InsertFailedException {
		return new StyleImpl(new StyleDAOImpl(ds, ObjectFactoryProperties.getString("ObjectFactoryProperties.DEFAULT_STYLE_NAME"), //$NON-NLS-1$
				ObjectFactoryProperties.getString("ObjectFactoryProperties.DEFAULT_STYLE_BRACKGROUNDCOLOR"), //$NON-NLS-1$
				ObjectFactoryProperties.getString("ObjectFactoryProperties.DEFAULT_STYLE_BRACKGROUNDIMAGE"))); //$NON-NLS-1$
	}

	/**
	 * This method returns a Style object.
	 * 
	 * @param name
	 * @param backgroundColor
	 * @param backgroundImage
	 * @return Style
	 * @throws InsertFailedException
	 */
	public static final Style createStyle(String name, String backgroundColor,
			String backgroundImage) throws InsertFailedException {
		return new StyleImpl(new StyleDAOImpl(ds, name, backgroundColor,
				backgroundImage));
	}

	/**
	 * This method returns a Tag object with default values.
	 * 
	 * @return Tag
	 * @throws InsertFailedException
	 */
	public static final Tag createTag() throws InsertFailedException {
		return new TagImpl(new TagDAOImpl(ds, ObjectFactoryProperties.getString("ObjectFactoryProperties.DEFAULT_TAG_KEYWORD"), //$NON-NLS-1$
				ObjectFactoryProperties.getString("ObjectFactoryProperties.DEFAULT_TAG_DESCRIPTION"))); //$NON-NLS-1$
	}

	/**
	 * This method returns a Tag object.
	 * 
	 * @param keyword
	 * @param description
	 * @return Tag
	 * @throws InsertFailedException
	 */
	public static final Tag createTag(String keyword, String description)
			throws InsertFailedException {
		if(keyword.contains("_")){
			keyword = keyword.replaceAll("_", " "); //Eine URI eines Tags wie z.B. "semantic web" wird zu ...tag/semantic_web -> d.h. tags duerfen keine "_" enthalten. "_" wird stumpf durch ein Leerzeichen ersetzt
		}
		return new TagImpl(new TagDAOImpl(ds, keyword, description));
	}

	/**
	 * This method returns a User object with default values.
	 * 
	 * @return User
	 * @throws InsertFailedException,
	 *             UpdateFailedException
	 * @throws DuplicateUsernameException 
	 */
	public static final User createUser(String userName) throws InsertFailedException,
			UpdateFailedException, DuplicateUsernameException {
		return new UserImpl(new UserDAOImpl(ds, userName, //$NON-NLS-1$
				ObjectFactoryProperties.getString("ObjectFactoryProperties.DEFAULT_USER_FIRSTNAME"), ObjectFactoryProperties.getString("ObjectFactoryProperties.DEFAULT_USER_LASTNAME"), //$NON-NLS-1$ //$NON-NLS-2$
				ObjectFactoryProperties.getString("ObjectFactoryProperties.DEFAULT_USER_EMAIL"), ObjectFactoryProperties.getString("ObjectFactoryProperties.DEFAULT_USER_PASSWORD"))); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * This method returns a User object.
	 * 
	 * @param userName
	 * @param firstName
	 * @param lastName
	 * @param email
	 * @param password
	 * @return User
	 * @throws InsertFailedException
	 * @throws UpdateFailedException
	 * @throws DuplicateUsernameException 
	 */
	public static final User createUser(String userName, String firstName,
			String lastName, String email, String password)
			throws InsertFailedException, UpdateFailedException, DuplicateUsernameException {
		return new UserImpl(new UserDAOImpl(ds, userName, firstName, lastName,
				email, password));
	}
	
	/**
	 * Returns the {@link User} object which corresponds to the given username.
	 * @param username the (unique) username
	 * @return the corresponding {@link User} object
	 * @throws UserNotExistingException 
	 */
	public static final User getUser(String username) throws UserNotExistingException {
		return new UserImpl(new UserDAOImpl(ds, username));
	}
	
	/**
	 * Returns the {@link User} object which corresponds to the given username.
	 * @param userID the (unique) ID of the user
	 * @return the corresponding {@link User} object
	 * @throws UserNotExistingException 
	 */
	public static final User getUser(Integer userID) throws UserNotExistingException {
		return new UserImpl(new UserDAOImpl(ds, userID));
	}
	
	/**
	 * Returns the Resource which corresponds to the given ID.
	 * @param id the ID of the Resource.
	 * @return the corresponding Resource.
	 */
	public static final Resource getResource(String id){
		return new ResourceImpl(new ResourceDAOImpl(ds, id));
	}
	
	/**
	 * Returns the Resource which corresponds to the given GroupMe! URI.
	 * @param uri the GroupMe! URI of the Resource.
	 * @return the corresponding Resource.
	 */
	public static final Resource getResourceByURI(URI uri){
		return new ResourceImpl(new ResourceDAOImpl(ds, StringUtilities.getIdFromURI(uri)));
	}
	
	/**
	 * Returns the Resource which corresponds to the given URL.
	 * @param url the URL of the Resource.
	 * @return the corresponding Resource or <code>null</code> if such a Resource does not exist.
	 */
	public static final Resource getResourceByURL(String url)
			throws InsertFailedException {
		//check if resource exists:
		String id = ResourceTools.doesResourceWithGivenUrlExists(url.toString());
		if(id != null){
			return getResource(id);
		}
		return null;
	}
	
	/**
	 * Returns the Group which corresponds to the given ID.
	 * @param id the ID of the Group.
	 * @return the corresponding Group.
	 */
	public static final Group getGroup(String id){
		return new GroupImpl(new GroupDAOImpl(ds, id));
	}
	
	/**
	 * Returns the Group which corresponds to the given ID.
	 * @param uriOfGroup the URI of the Group.
	 * @return the corresponding Group.
	 */
	public static final Group getGroup(URI uriOfGroup){
		return new GroupImpl(new GroupDAOImpl(ds, StringUtilities.getIdFromURI(uriOfGroup)));
	}
	
	/**
	 * Returns the ResourceVisualization which corresponds to the given ID.
	 * @param id the ID of the ResourceVisualization.
	 * @return the corresponding ResourceVisualization.
	 */
	public static final ResourceVisualization getResourceVisualization(String id){
		return new ResourceVisualizationImpl(new ResourceVisualizationDAOImpl(ds, id));
	}
	
	/**
	 * Returns the ResourceVisualization which corresponds to the given ID.
	 * @param id the ID of the ResourceVisualization.
	 * @return the corresponding ResourceVisualization.
	 */
	public static final ResourceVisualization getResourceVisualization(URI uriOfResViso){
		return new ResourceVisualizationImpl(new ResourceVisualizationDAOImpl(ds, StringUtilities.getIdFromURI(uriOfResViso)));
	}
	
	/**
	 * This method return the corresponding Tag for a keyword. If the Tag is not
	 * available, a new one is created.
	 * 
	 * @param keyword the keyword of the Tag
	 * @return the Tag
	 * @throws InsertFailedException 
	 */
	@SuppressWarnings("unchecked")
	public static final Tag getTagForKeyword(String keyword) throws InsertFailedException{
		GetTagsQuery getTagsQuery = new GetTagsQuery(ds);
		Object[] params = new Object[1];
		
		params[0]= keyword;
		
		
		Iterator iter = getTagsQuery.execute(params).iterator();
		if (iter.hasNext()) {
			return ((Collection<Tag>) iter.next()).iterator().next();
		}
		return ObjectFactory.createTag(keyword.trim().toLowerCase(), "");
	}
	
	/**
	 * This method return the corresponding Tag for a keyword. If the Tag is not
	 * available, then a new Tag is inserted into the DB and will be returned.
	 * 
	 * @param keyword the keyword of the Tag
	 * @return the corresponding tag 
	 */
	@SuppressWarnings("unchecked")
	public static final Tag getTag(String keyword){
		String query = "SELECT " + TAG_ID + " FROM " + TABLE_TAG + " WHERE " 
			+ TAG_KEYWORD + " = \"" + keyword + "\"";
		GetTagsQuery getTagsQuery = new GetTagsQuery(ds, query,	TAG_ID);
		Iterator iter = getTagsQuery.execute().iterator();
		if (iter.hasNext()) {
			return ((Collection<Tag>) iter.next()).iterator().next();
		}
		try {
			return ObjectFactory.createTag(keyword.trim().toLowerCase(), "");
		} catch (InsertFailedException e) {
			e.printStackTrace();
			return null;
		}
	}
	
	/**
	 * This method return the corresponding Tag for a keyword. If the Tag is not
	 * available, then {@link ObjectFactory#getInMemoryGroup(String, String, String)}, where id is set to <i>-1</i>.
	 * 
	 * @param keyword the keyword of the Tag
	 * @return the corresponding tag or an {@link TagDAOMemImpl} instance with an id of <i>-1</i>
	 */
	@SuppressWarnings("unchecked")
	public static final Tag getTagIfExist(String keyword){
		GetTagsQuery getTagsQuery = new GetTagsQuery(ds);
		Object[] params = new Object[1];
		params[0]= keyword;
		Iterator iter = getTagsQuery.execute(params).iterator();
		if (iter.hasNext()) {
			return ((Collection<Tag>) iter.next()).iterator().next();
		}
		return ObjectFactory.getInMemoryTag("-1", keyword, null);

	}
	
	/**
	 * This method returns the reference to a Tag object with
	 * the given id (if the ID of the Tag does not exist then you
	 * will recognize it awhen calling a getter or setter).
	 * 
	 * @param id the id of the Tag
	 * @return the corresponding tag
	 */
	@SuppressWarnings("unchecked")
	public static final Tag getTagById(String id){
		return new TagImpl(new TagDAOImpl(ds, id));
	}
	
	/**
	 * This method returns the reference to a Tag object with
	 * the given id, keyword and description. 
	 * 
	 * Use this factory-method in order to reduce database traffic.
	 * 
	 * @param id the id of the Tag
	 * @param keyword the actual tag
	 * @param description an optional description
	 * @return the corresponding tag
	 */
	@SuppressWarnings("unchecked")
	public static final Tag getTagByIdKeyWordAndDescription(String id, String keyword, String description){
		return new TagImpl(new TagDAOImpl(ds, id, keyword, description));
	}
	
	/**
	 * Returns a cached object which reflects the given objectToCache to the underlying
	 * database.
	 * @param objectToCache the object to cache
	 * @param type the (semantic) type of the object to cache (e.g. tag cloud, ..)
	 * @return a new cached object which reflects the given objectToCache to the underlying
	 * database.
	 */
	public static final CachedObject createCachedObject(Cachable objectToCache, CachedObjectType type){
		try {
			return new CachedObjectDAOImpl(ds, objectToCache, type);
		} catch (InsertFailedException e) {
			e.printStackTrace();
			logger.error("Failed to save the object that should be cached.", e);
			return null;
		}
	}
	
	/**
	 * Returns a cached object which reflects the given objectToCache to the underlying
	 * database.
	 * @param objectToCache the object to cache
	 * @param user the user for whom the object is cached
	 * @param type the (semantic) type of the object to cache (e.g. tag cloud, ..)
	 * @return a new cached object which reflects the given objectToCache to the underlying
	 * database.
	 */
	public static final CachedObject createCachedObject(Cachable objectToCache, User user, CachedObjectType type){
		try {
			return new CachedObjectDAOImpl(ds, user, objectToCache, type);
		} catch (InsertFailedException e) {
			e.printStackTrace();
			logger.error("Failed to save the object that should be cached.", e);
			return null;
		}
	}
	
	/**
	 * Returns a cached object which reflects the given objectToCache to the underlying
	 * database.
	 * @param objectToCache the object to cache
	 * @param user the user for whom the object is cached
	 * @param type the (semantic) type of the object to cache (e.g. tag cloud, ..)
	 * @param relatedWith the URI of the context (e.g. a group) in which the given object belongs to 
	 * @return a new cached object which reflects the given objectToCache to the underlying
	 * database.
	 */
	public static final CachedObject createCachedObject(Cachable objectToCache, User user, CachedObjectType type, URI relatedWith){
		try {
			return new CachedObjectDAOImpl(ds, user, objectToCache, type, relatedWith);
		} catch (InsertFailedException e) {
			e.printStackTrace();
			logger.error("Failed to save the object that should be cached.", e);
			return null;
		}
	}
	
	
	/**
	 * Returns a cached object which has the given type (and user and is related with the given URI) 
	 * or <code>null</code> if no object that has this type is cached in the database.
	 * 
	 * @param type the (semantic) type of the object that is cached 
	 * @param user the user for whom the object is cached (can be <code>null</code>)
	 * @param relatedWith the URI of the context (e.g. a group) in which the given object belongs to (can be <code>null</code>)
	 * @return a cached object which has the given type or <code>null</code> if no
	 * object that has this type is cached in the database.
	 */
	public static final CachedObject getCachedObject(CachedObjectType type, User user, URI relatedWith){
		int id = SelectQueryUtility.NO_RESULT_SET_FOUND;
		if(user == null && relatedWith == null){
			id = CacheQueryUtility.getIdOfCachedObject(type);
		}else if(relatedWith == null){
			id = CacheQueryUtility.getIdOfCachedObject(type, user);
		}else if(user == null){
			id = CacheQueryUtility.getIdOfCachedObject(type, relatedWith);
		}else {
			id = CacheQueryUtility.getIdOfCachedObject(type, user, relatedWith);
		}
		logger.info("ID of Cached Object: " + id);
		
		if(id == SelectQueryUtility.NO_RESULT_SET_FOUND){
			return null;
		}
		return new CachedObjectDAOImpl(ds, id);
	}
	
	/**
	 * Returns an In-Memory-Resource which has the given values...
	 * @param id the id
	 * @param name the name
	 * @param description the description
	 * @param url url of the resource
	 * @param type type of resource (e.g. group, website,..)
	 * @return the corresponding Resource.
	 */
	public static final Resource getInMemoryResource(String id, String name, String description, URL url, String type) {
		return new ResourceImpl(new ResourceDAOMemImpl(id, name, description, url, type));
	}
	
	/**
	 * Returns an In-Memory-Resource which has the given values and a valid id (which means that 
	 * the id refers to the right resource in the database...)
	 * @param name the name
	 * @param description the description
	 * @param url url of the resource
	 * @param type type of resource (e.g. group, website,..)
	 * @return the corresponding Resource.
	 * @throws InsertFailedException problems while checking for the ID 
	 */
	public static final Resource getInMemoryResourceWithValidId(String name, String description, URL url, String type) throws InsertFailedException {
		return new ResourceImpl(new ResourceDAOMemImpl(createResource(name, description, type, url).getId(), name, description, url, type));
	}
	
	/**
	 * Returns an In-Memory-Group which has the given values...
	 * @param id
	 * @param name
	 * @param description
	 * @param url
	 * @param type
	 * @return the corresponding Group.
	 */
	public static final Group getInMemoryGroup(String id, String name, String description){
		return new GroupImpl(new GroupDAOMemImpl(id, name, description));
	}
	
	/**
	 * Returns an In-Memory-Tag which has the given values...
	 * @param id the id of the tag
	 * @param keyword the actual tag
	 * @param description a description (optional)
	 * @return the corresponding Tag.
	 */
	public static final Tag getInMemoryTag(String id, String keyword, String description) {
		return new TagImpl(new TagDAOMemImpl(id, keyword, description));
	}
	/**
	 * This method first extracts the data from the DB using {@link TagDAOImpl} and then converts it
	 * to a {@link TagDAOMemImpl} instance.
	 * @param keyword the tag-keyword
	 * @return a {@link TagDAOImpl} instance that wraps the given keyword
	 */
	public static final Tag getInMemoryTag(String keyword){
		Tag tmp = getTag(keyword);
		return getInMemoryTag(tmp.getId(), tmp.getKeyword(), tmp.getDescription());
	}
	/**
	 * This methods expects a valid id, username, etc. and returns it as an in-memory user
	 * @param id
	 * @param username
	 * @param firstname
	 * @param lastname
	 * @param email
	 * @return
	 */
	public static final User getInMemoryUser(String id, String username, String firstname, String lastname, String email) {
		return new UserImpl(new UserDAOMemImpl(id, username, firstname, lastname, email));
	}
	
	/**
	 * Returns an In-Memory implementation of a ResourceVisualization with a valid database id.
	 * @param groupVisu the corresponding group visualization
	 * @param resource the resource that is visualized
	 * @param posX position on x axis
	 * @param posY position on y axis
	 * @param width the width of the resource
	 * @param height the height of the resource
	 * @return an In-Memory implementation of a ResourceVisualization with a valid database id.
	 * @throws InsertFailedException problems while checking for the ID 
	 */
	public static final ResourceVisualization getInMemoryResourceVisualizationWithValidId(GroupVisualization groupVisu, Resource resource, int posX, int posY,
			int width, int height)  throws InsertFailedException {
		return new GameResourceVisualizationImpl(new ResourceVisualizationDAOMemImpl(width, height, posX, posY, createResourceVisualization(groupVisu, resource).getId()));
	}
	
	/**
	 * This method returns a GroupVisualization object with a valid database id.
	 * @param group the group that is visualized
	 * @return GroupVisualization a GroupVisualization object with a valid database id.
	 * @throws InsertFailedException problems while checking for the ID 
	 */
	public static final GroupVisualization getInMemoryGroupVisualization(Group group) throws InsertFailedException {
		return new GroupVisualizationImpl(new GroupVisualizationDAOMemImpl(group, createGroupVisualization().getId()));
	}
	
	/**
	 * This method returns a totally In-Memory version of a GroupVisualization object (without valid database id!).
	 * @param name the name of the group visualization
	 * @param description short description of the visualization
	 * @param group the group that is visualized
	 * @return a totally In-Memory version of a GroupVisualization object (without valid database id!).
	 */
	public static final GroupVisualization getInMemoryGroupVisualization(String name, String description, Group group)  {
		return new GroupVisualizationImpl(new GroupVisualizationDAOMemImpl(name, description, group));
	}
	
	/**
	 * Returns a totally In-Memory implementation of a ResourceVisualization (without valid database id).
	 * @param groupVisu the corresponding group visualization
	 * @param resource the resource that is visualized
	 * @return a totally In-Memory implementation of a ResourceVisualization (without valid database id)
	 */
	public static final ResourceVisualization getInMemoryResourceVisualization(GroupVisualization groupVisu, Resource resource) {
		return new ResourceVisualizationImpl(new ResourceVisualizationDAOMemImpl(groupVisu, resource));
	}
}
